home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / VideoToolbox 96.06.15 / VideoToolboxSources / SndPlay1.c < prev    next >
Text File  |  1996-06-06  |  5KB  |  134 lines

  1. /* 
  2. SndPlay1.c
  3.  
  4. SndPlay1(snd) plays a sound, asynchronously, i.e. it returns immediately, while the
  5. sound is still playing. The argument is a handle to a snd resource. If a sound is 
  6. still playing from a previous call to SndPlay1, it is allowed to finish before
  7. SndPlay1 closes and reopens the channel and begins the new sound.
  8. SndPlay1(NULL) waits for any previously SndPlay1-initiated sound to end and then closes the channel.
  9. SndStop1() closes the channel immediately.
  10. SndDone1() returns true if the last sound initiated by SndPlay1() has finished.
  11.  
  12. Apple advises against leaving the channel open for extended periods, because the open 
  13. channel blocks SysBeep. To minimize this, make sure to call SndPlay1(NULL) or SndStop1() 
  14. to close the channel when you no longer need it.
  15.  
  16. The easiest way to get a sound that you can play is to call GetNamedResource(). 
  17. Here's a complete program to get a sound and play it.
  18.     Handle snd;
  19.     snd=GetNamedResource('snd ',"\pSimple Beep");
  20.     SndPlay1(snd);    // start snd playing, and return immediately, while it's playing
  21.     // do something useful here
  22.     SndPlay1(NULL);    // wait till snd is done, then close and dispose of sound channel
  23.     ReleaseResource(snd);
  24. It's also easy to create your own snd in memory, as a series of commands,
  25. following the instructions in Inside Mac:Sound. Use VideoToolbox CreateTrialsSnds.c as an example.
  26.  
  27. As of 1994, the Apple Sound Manager has the annoying characteristic of insisting on loading
  28. any synth that's mentioned in a snd resource, even if that synth is already loaded,
  29. which causes an error. This makes it necessary to dispose of and recreate the 
  30. snd channel before each new sound, which these routines do. 
  31.  
  32. NOTE: The snd is not locked while being played. I don't know whether that's necessary.
  33. It seems to work ok as is, on both 68k and ppc machines, but I haven't stressed it. In
  34. particular, I don't move memory while the sound is playing. I probably ought to lock it
  35. down and HoldMemory on the snd while it's playing. However, that would complicate the
  36. program slightly, since the locking and unlocking would have to happen in different
  37. routines, below, and the address of the snd would have to be communicated between them, 
  38. presumably by a variable global to this file.
  39.  
  40. HISTORY:
  41. 3/30/92    dgp wrote it.
  42. 4/1/92    dgp    renamed it and commented out the printf's.
  43. 7/9/93    dgp Test MATLAB in if() instead of #if. 
  44. 5/28/94 dgp Made compatible with Apple's Universal Headers. Thanks to Bob Dougherty 
  45. (wolfgang@cats.ucsc.edu) for reporting the incompatibility.
  46. 9/5/94 dgp removed assumption in printf's that int==short.
  47. 9/10/94 dgp cosmetic
  48. 10/5/94 dgp simplified SndCallBack1 until it stopped crashing when I run native on ppc.
  49. 10/27/94 dgp It is very annoying for the machine to crash anytime you try to quit your
  50. application by escaping via MacsBugs escape to shell. The problem is that CodeWarrior 
  51. doesn't attach the atexit() tasks to _EscapeToShell. So I do it here. 
  52. 7/1/95 dgp just call AtExitToShell(), without any conditionals. Special cases, e.g. MATLAB,
  53. are handled in AtExitToShell.c.
  54. */
  55. #include "VideoToolbox.h"
  56. //#include <Sound.h>
  57. static pascal void SndCallBack1(SndChannelPtr channelPtr,SndCommand command);
  58. static SndChannel *channelPtr=NULL,channel;
  59. static SndCommand callBack;
  60. #if !UNIVERSAL_HEADERS
  61.     #define NewSndCallBackProc (SndCallBackUPP)
  62.     typedef ProcPtr SndCallBackUPP;
  63. #endif
  64. #if UNIVERSAL_HEADERS<2
  65.     #define SndListHandle Handle
  66. #endif
  67.  
  68. OSErr SndPlay1(Handle snd)
  69. {
  70.     int error=0;
  71.     static Boolean firstTime=1;
  72.     static SndCallBackUPP sndCallBackProc;
  73.  
  74.     if(snd!=NULL)HNoPurge(snd); // make sure snd is not purged while we're allocating memory
  75.     if(firstTime){
  76.         sndCallBackProc=NewSndCallBackProc(SndCallBack1);
  77.         AtExitToShell(SndStop1);
  78.         firstTime=0;
  79.     }
  80.     if(channelPtr!=NULL)error=SndDisposeChannel(channelPtr,FALSE);    // wait till done
  81.     channelPtr=NULL;
  82.     if(error)return error;
  83.     if(snd==NULL)return 0;
  84.     if(1)error=SndNewChannel(&channelPtr,0,0L,sndCallBackProc);    // allocates space for 128 snds.
  85.     else{
  86.         channelPtr=&channel;
  87.         channelPtr->qLength=10;    // how many snd commands to allow space for. CreateTrialSnds.c snds use 4.
  88.         error=SndNewChannel(&channelPtr,0,0L,sndCallBackProc);
  89.         if(error)channelPtr=NULL;
  90.     }
  91.     if(error){
  92.         printf("%s %d:SndNewChannel failed with error %d\007\n",__FILE__,__LINE__,error);
  93.         return error;
  94.     }
  95.     error=SndPlay(channelPtr,(SndListHandle)snd,TRUE);
  96.     if(error){
  97.         printf("%s %d:SndPlay failed with error %d\007\n",__FILE__,__LINE__,error);
  98.         return error;
  99.     }
  100.     callBack.cmd=callBackCmd;
  101.     callBack.param1=0;
  102.     error=SndDoCommand(channelPtr,&callBack,FALSE);
  103.     if(error)printf("%s %d:SndDoCommand failed with error %d\007\n",__FILE__,__LINE__,error);
  104.     return error;
  105. }
  106.  
  107. void SndStop1(void)
  108. {
  109.     if(channelPtr!=NULL)SndDisposeChannel(channelPtr,TRUE);        // immediately
  110.     channelPtr=NULL;
  111. }
  112.  
  113. short SndDone1(void)
  114. // Returns 1 if the last sound initiated by SndPlay1 has finished. Otherwise 0.
  115. {
  116.     return callBack.param1;
  117. }
  118.  
  119. #if (THINK_C || THINK_CPLUS || SYMANTEC_C)
  120.     #pragma options(!profile)    // Disable profiling because A5 may be invalid.
  121. #endif
  122. #if __MWERKS__ && __profile__
  123.     #pragma profile off            // on 68k it would be dangerous to call the profiler from here
  124. #endif
  125.  
  126. static pascal void SndCallBack1(SndChannelPtr channelPtr,SndCommand command)
  127. // Load a short int.
  128. // Called back by sound manager.  Lets us know when sound is done.
  129. {
  130.     channelPtr;    // prevent "unused argument" warning
  131.     command.param1=1;
  132. }
  133.  
  134.